﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Asteroids.Game
{
    public class Weapon : IUpdate
    {
        public Ammo CurrentAmmo { get; set; }
        public List<WeaponBuff> CurrentBuffs { get; set; }
        public Coordinate Location { get; set; }
        public double AccuracyRating { get; set; }
        public int RateOfFire { get; set; }
        public int CoolDown { get; set; }

        public Weapon(Coordinate loc)
        {
            Location = loc;
            CurrentAmmo = Ammo.Missile;
            CurrentBuffs = new List<WeaponBuff>();
            AccuracyRating = 0.05;
            RateOfFire = 3;
            CoolDown = RateOfFire;
        }

        public void Update(UpdateEventArgs e)
        {
            CoolDown++;
        }

        public void Fire(double shipDirection)
        {
            if (CoolDown > RateOfFire)
            {
                var currentShots = new List<Projectile>();
                currentShots.AddRange(GetAllProjectiles(shipDirection));
                Game.Instance.PlayerShotsFired.AddRange(currentShots);
                CoolDown = 0;
            }
        }

        private List<Projectile> GetAllProjectiles(double shipDirection)
        {
            const double angleTriShot = Math.PI/18;
            int numProjectiles = 1;
            bool isBurst = false;
            foreach (var currentBuff in CurrentBuffs)
            {
                if (currentBuff == WeaponBuff.Trishot)
                    numProjectiles *= 3;
                else if (currentBuff == WeaponBuff.Burst)
                {
                    numProjectiles *= 9;
                    isBurst = true;
                }
            }
            var ret = new List<Projectile>();

            for (var i = 0; i < numProjectiles; i++)
            {
                var p = GetProjectile();
                p.Location = Location;
                if (isBurst)
                {
                    p.FaceDirection = shipDirection + (i * (Math.PI * 2 / numProjectiles));
                }
                else
                {
                    p.FaceDirection = shipDirection + (angleTriShot * (i - (numProjectiles - 1) / 2));
                }
                p.Velocity.Angle = p.FaceDirection;

                ret.Add(p);
            }

            return ret;
        }

        private Projectile GetProjectile()
        {
            switch (CurrentAmmo)
            {
                case Ammo.Nuke:
                    return new Nuke(new Coordinate(0,0), 0);
                case Ammo.Missile:
                    return new Missile(new Coordinate(0, 0), 0);
                case Ammo.Beam:
                    return new Beam(new Coordinate(0, 0), 0);
                default:
                    throw new NotImplementedException();
            }
        }
    }

    public enum Ammo
    {
        Missile,
        Beam,
        Nuke,
    }

    public enum WeaponBuff
    {
        Trishot,
        Burst,
    }
}
